// SPDX-License-Identifier: GPL-2.0

#include <linux/types.h>
#include <linux/bits.h>
#include <linux/err.h>
#include <linux/tpm.h>
#include <linux/crypto.h>
#include "dim_tpm.h"

static struct tpm_chip *chip;
static struct tpm_digest *digests;
static int tpm_alg;
static int digest_size = DIM_DIGEST_SIZE;

int dim_tpm_chip_init(void)
{
	int i;

	if (chip == NULL) {
		chip = tpm_default_chip();
		if (chip == NULL)
			return -ENODEV;
	}

	digests = kcalloc(chip->nr_allocated_banks,
		sizeof(*digests), GFP_KERNEL);
	if (digests == NULL)
		return -ENOMEM;

	tpm_alg = -1;
	for (i = 0; i < chip->nr_allocated_banks; i++) {
		digests[i].alg_id = chip->allocated_banks[i].alg_id;
		if (chip->allocated_banks[i].crypto_id == HASH_ALGO_SHA256)
			tpm_alg = i;

		memset(digests[i].digest, 0xff, TPM_MAX_DIGEST_SIZE);
	}

	if (tpm_alg == -1) {
		kfree(digests);
		digests = NULL;
		return -EINVAL;
	}

	return 0;
}

void dim_tpm_chip_uninit(void)
{
	kfree(digests);
	digests = NULL;
	chip = NULL;
}

int dim_tpm_pcr_extend(char *hash, int len)
{
	if (chip == NULL)
		return -ENODEV;

	if (hash == NULL || len != digest_size)
		return -EINVAL;

	memcpy(digests[tpm_alg].digest, hash, len);

	return tpm_pcr_extend(chip, DIM_TPM_PCR, digests);
}
